本文将基于JDK25最新源码,对AbstractSelector进行原子级的解构。 volatileboolean+VarHandle直接嵌入AbstractSelector实例中,零额外对象开销,缓存行利用率更高。 AbstractSelector的interruptor就是这条链路的枢纽。 AbstractSelector的中断协议因此成为了传统线程与虚拟线程共享的基础设施。 随着ProjectLoom的成熟和io_uring等新I/O原语的引入,AbstractSelector的实现细节将继续演化。
null); } @Override public ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector Override public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector null); } public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector
null); } @Override public ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector Override public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector null); } public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector
跳过抽象层:AbstractSelector.cancel()是一个同步方法(见下文),它会获取cancelledKeys集合的锁。 减少对象创建:AbstractSelector.cancel()可能需要将Key包装或转换,而直接调用可以避免这些中间对象。 路径二:AbstractSelector通用路径对于第三方Selector实现(如Netty的自定义Selector、AIOSelector等),它们继承自AbstractSelector而非SelectorImpl 第五章:与AbstractSelector和AbstractSelectableChannel的协同AbstractSelectionKey不是孤立存在的。 渐进式抽象:保留SPI扩展点(AbstractSelector路径),同时为常见场景提供特化优化(SelectorImpl路径)。
extends SelectorProviderImpl { public WindowsSelectorProvider() { } // 获得选择器 public AbstractSelector
interruptor.interrupt(me); } 2.如果线程阻塞在Selector,执行它的 wakeup方法,因而selector会立即返回,同时会设置中断标志 //AbstractSelector public void interrupt(Thread ignore) { //执行wakeup,Selector立即返回 AbstractSelector.this.wakeup
SelectorProvider.provider().openSelector(); } linux中是EPollSelectorProvider, 该openSelector方法为: public AbstractSelector isOpen()) throw new ClosedChannelException(); k = ((AbstractSelector
null); } public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector " + exception.getMessage()); } //...... } getServiceList方法有个AbstractSelector
null); } public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector : " + exception.getMessage()); } //...... } getServiceList方法有个AbstractSelector
可以有多个SelectionKey, 代表一个Channel可以有多个Selector, 1:N 图片 // 选择器类 public abstract class SelectorImpl extends AbstractSelector
com.alibaba.nacos.api.naming.pojo.ListView; import com.alibaba.nacos.api.naming.pojo.ServiceInfo; import com.alibaba.nacos.api.selector.AbstractSelector listView; } @Override public ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector Override public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector
private Selector selector; 那么我们简单看一下这个Selector在JDK层面的实现 public abstract class SelectorImpl extends AbstractSelector
*/ public class EPollSelectorProvider extends SelectorProviderImpl { public AbstractSelector openSelector pollWrapper.initInterrupt(fd0, fd1); fdToKey = new HashMap<>(); } } public abstract class SelectorImpl extends AbstractSelector isOpen()) throw new ClosedChannelException(); k = ((AbstractSelector (k); } } return k; } } } public abstract class AbstractSelector int ops, Object att); } public abstract class SelectorImpl extends AbstractSelector
注意openSelector()返回的是AbstractSelector而非Selector——这是因为AbstractSelector包含了中断协议和取消键管理等SPI级别的实现细节,子类必须继承它。 返回正确的抽象类型:openSelector()必须返回AbstractSelector的子类。
先找到AbstractSelectableChannel.register方法,定位到((AbstractSelector)sel).register(this, ops, att)找到SelectorImpl.register throw new ClosedChannelException(); //register方法 k = ((AbstractSelector
SelectionKey 集合 : 存储有事件发生的 通道 ( Channel ) 对应的 SelectionKey ; public abstract class SelectorImpl extends AbstractSelector
ClosedChannelException(); // 注册channel到selector并返回选择SelectionKey k = ((AbstractSelector
EPollSelectorProvider public class EPollSelectorProvider extends SelectorProviderImpl { public AbstractSelector isOpen()) throw new ClosedChannelException(); k = ((AbstractSelector
例如removeKey(SelectionKeyk)方法是包级私有的,因为它只应由同包下的AbstractSelector在取消注册时调用,普通用户不应也无法直接干预Key的内部移除过程。 **包级私有可见性**:如前所述,它只允许同包的`AbstractSelector`调用。这防止了用户代码意外或恶意地破坏通道内部的Key一致性。2. =null){//第七步:更新已有Keyk.attach(att);k.interestOps(ops);}else{//第八步:创建新Key(委托给Selector)k=((AbstractSelector ####4.2.4委托注册与双向绑定`((AbstractSelector)sel).register(this,ops,att)`这一行揭示了Channel与Selector之间的双向协作关系。
1.2SPI包的访问控制哲学展开代码语言:TXTAI代码解释publicabstractclassAsynchronousChannelProvider注意该类是publicabstract,而非像AbstractSelector